using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Messaging;
using System.Configuration;
namespace WindowsService
{
    class WindowsService : ServiceBase
    {
        /// <summary>
        /// Public Constructor for WindowsService.
        /// 
        /// </summary>
        #region variable decl
        string abuffer = String.Empty;
        AutoResetEvent waithandle;
        SerialPort port;
        private MessageQueue messageQueue = null;
        const string pathQueue = @".\Private$\PortQueue";
        #endregion
        public WindowsService()
        {
            string portName;
            int baudRate;
            int dataBit;
            initService();
           // if (!EventLog.SourceExists("Read Card Service"))
              //  EventLog.CreateEventSource("Read Card Service", "Application");

            waithandle = new AutoResetEvent(false);
            // create queue
            if (MessageQueue.Exists(pathQueue))
                messageQueue = new MessageQueue(pathQueue);
            else
                messageQueue = MessageQueue.Create(pathQueue);

            try
            {
                portName = ConfigurationManager.AppSettings["PortName"];
                baudRate = Int32.Parse(ConfigurationManager.AppSettings["BaudRate"]);
                dataBit = Int32.Parse(ConfigurationManager.AppSettings["DataBit"]);

                port = new SerialPort(portName, baudRate, Parity.None, dataBit, StopBits.One);
                port.Handshake = Handshake.None;
                port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
             
            }
            catch (Exception e)
            {
                EventLog.WriteEntry("Error", e.Message);
            }
        }
        /**
         *setting for service 
         */
        public void initService()
        {
            this.ServiceName = "Read Card Service";
            //this.EventLog.Source = "Read Card Service";
           // this.EventLog.Log = "Application";


            // These Flags set whether or not to handle that specific
            //  type of event. Set to true if you need it, false otherwise.
            this.CanHandlePowerEvent = true;
            this.CanHandleSessionChangeEvent = true;
            this.CanPauseAndContinue = true;
            this.CanShutdown = true;
            this.CanStop = true;
        }

        /// <summary>
        /// The Main Thread: This is where your Service is Run.
        /// </summary>
        static void Main()
        {
            ServiceBase.Run(new WindowsService());
        }

        /// <summary>
        /// Dispose of objects that need it here.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        /// <summary>
        /// OnStart: Put startup code here
        /// Start threads, get inital data, etc.
        /// </summary>
        protected override void OnStart(string[] args)
        {
            base.OnStart(args);
            //EventLog.WriteEntry("My Windows Service", "OnStart service");
            this.Open();
            EventLog.WriteEntry("My Windows Service", "OnStart service");
            new Thread(new System.Threading.ThreadStart(readMessage)).Start();
           
        }

        /// <summary>
        /// OnStop: Put your stop code here
        /// Stop threads, set final data, etc.
        /// </summary>
        protected override void OnStop()
        {
            base.OnStop();
            this.Close();
        }

        /// <summary>
        /// OnPause: Put your pause code here
        /// Pause working threads, etc.
        /// </summary>
        protected override void OnPause()
        {
            base.OnPause();
        }

        /// <summary>
        /// OnContinue: Put your continue code here
        /// Un-pause working threads, etc.
        /// </summary>
        protected override void OnContinue()
        {
            base.OnContinue();
           
        }

        /// <summary>
        /// OnShutdown(): Called when the System is shutting down   
        /// </summary>
        protected override void OnShutdown()
        {
            base.OnShutdown();
        }

        /// <summary>
        /// OnCustomCommand(): If you need to send a command to your
        ///   service without the need for Remoting or Sockets, use
        ///   this method to do custom methods.
        /// </summary>
        protected override void OnCustomCommand(int command)
        {
            base.OnCustomCommand(command);
        }

        /// <summary>
        /// OnPowerEvent(): Useful for detecting power status changes,
        ///   such as going into Suspend mode or Low Battery for laptops.
        /// </summary>
        protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
        {
            return base.OnPowerEvent(powerStatus);
        }

        /// <summary>
        /// OnSessionChange(): To handle a change event from a Terminal Server session.
        /// </summary>
        protected override void OnSessionChange(SessionChangeDescription changeDescription)
        {
            base.OnSessionChange(changeDescription);
        }
        /**
        * setting for port
        */
        public void Setting(int baudRate, Parity parity, int databit, StopBits stopBit)
        {

            port.BaudRate = baudRate;
            port.Parity = parity;
            port.DataBits = databit;
            port.StopBits = stopBit;
        }
        public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort serialP = (SerialPort)sender;
            if(e.EventType == SerialData.Chars)
                waithandle.Set();

        }
        public void Open()
        {
            if (port.IsOpen == false)
            {
                port.Open();
            }
        }
        public void Close()
        {
            if (port.IsOpen == true)
            {
                port.Close();
            }
        }
        /// <summary>
        /// read data in port 
        /// </summary>
        public void readMessage()
        {
            Message mssSend;
            do
            {
                waithandle.WaitOne();
                Thread.Sleep(5000);
                this.abuffer += port.ReadExisting();
                if (!abuffer.Equals(""))
                {
                    System.Diagnostics.EventLog.WriteEntry("Result", abuffer);
                    mssSend = new Message();
                    mssSend.Body = this.abuffer;
                    mssSend.Label = "CardID";
                    messageQueue.Send(mssSend);
                }
                this.abuffer = "";
            } while (port != null && port.IsOpen);
            
        }
    }
}
